namespace ghost {
	/**场景业务角色，游戏的角色的公共业务内容都编写于此，其他特殊功能都是继承此类扩展*/
	export class GameRole extends AniRole{						
		public constructor(sceneMgr:SceneManager) {
			super(sceneMgr);
			let s = this;			
			s._targetRoles = [];
			s._targetIds = [];				
			s._bodyRange = [];			
			s._numberList = [];
			s.setRange(5000000,5000000);
			s.init();
		}
		protected init():void
		{
			let s= this;						
			s.moveTimeTicker = new map2D.TimeTicker(s._scene);
			s._skillList = [];			
			s._skillCDList = {};
			s._skillPreCDList = {};
			s._lastSkillFailList = {};
			s.buffValues = [];
			s.buffList = [];
			s.buffObjs = [];
		}	
		public setRange(viewRange:number, territoryRange:number):void
		{
			let s = this;
			s.viewRange = viewRange;
			s.territoryRange = territoryRange;
			s._territoryRange2 = s.territoryRange*s.territoryRange;			
			s._viewRange2 = s.viewRange*s.viewRange;
		}
		public pause(includeMyObj:boolean = false):void
		{
			super.pause();
			let s= this;
			if(includeMyObj)											
				Effect.pause(s._id);
		}
		public resume(includeMyObj:boolean = false):void
		{
			let s = this;							
			super.resume();		
			if(includeMyObj)			
				Effect.resume(s._id);
		}
		
		protected setConfig(cfg:any):void
		{
			let s = this;
			super.setConfig(cfg);
			if(cfg.smart)
				s.changeSmart(cfg.smart);
			// s._smartFunc = s[cfg.smart];
		}
		public resetSts():void
		{
			super.resetSts();
			let s= this;
			s.resetingSts();
		}
		protected resetingSts(): void {
			let s = this;			
			if(s._stsChangeBeforeReset)return;//防止resetSts方法里面的_stsEndListener.dataChange回调修改了动作状态，如修改了则不进行状态恢复			
			if(s._sts == StsType.DEATH)
			{
				if(!s._canRevive)						
					s.del();
				return;
			}
			let targets:GameRole[] = s.getAtkTarget();
			if(s.isEnemyMonster() && targets[0] && !targets[0]._isDead && !targets[0].isDel())//仍然有目标持续保持攻击状态
			{					
				s.addHitToTarget(targets[0]);
				s.setSts(StsType.ATTACK);				
			}					
			else
				s.setSts(StsType.STAND);
				
		}
		/**根据id释放MMO技能*/
		public operSkillId(skillId:number):void
		{
			let s = this;
			let len:number;
			len = s._skillList.length;
			while(--len>-1)
			{
				if(s._skillList[len].skillId == skillId)
				{
					s.operSkill(s._skillList[len]);
					return;
				}					
			}
			// Log.writeLog("释放技能列表不存在的技能:" + skillId, Log.ERROR);
		}		
		/**设置技能cd*/
		public cdSkill(skill:ISkillData):void
		{
			let s= this;
			let t:number;
			t = s._scene.timeTick;
			// if(s._skillPreCDList[skill.skillId] == null)
			// 	s._skillPreCDList[skill.skillId] = t;
			s._skillCDList[skill.skillId] = t;
		}
		public isCDOk(skill:ISkillData):boolean
		{
			let s= this;
			let t:number;
			let skillCD:number,skillPreCD:number;			
			skillCD = s._skillCDList[skill.skillId]?s._skillCDList[skill.skillId]:0;
			skillPreCD = s._skillPreCDList[skill.skillId]?s._skillPreCDList[skill.skillId]:0;
			t = s._scene.timeTick;
			let cd:number = Math.max(CommonUtil.delta, skill.cd * (1-s.cdReduce));
			// && t - skillPreCD >= skill.preCD
			return t - skillCD >= cd;
		}
		/**我是否处于我的领地范围*/
		public inMyTerritoryRange():boolean
		{
			let s = this;
			let dis:number;			
			dis = PositionUtil.calculateDistance2(s._absX,s._absY,s._bornX,s._bornY);
			return s._territoryRange2 > dis;
		}
		/**获取冷却结束且优先级最高的技能*/
		public getProritySkill(target:GameRole):ISkillData
		{
			let s = this;
			//判断所有技能是否存在攻击范围内且冷却已经好了的
			let skill:ISkillData;
			let i:number,len:number;		
			let t:number;
			
			t = s._scene.timeTick;	
			len = s._skillList.length;
			for(i=0;i<len;++i)
			{
				skill = s._skillList[i];
				if(skill.skillCfg.priority == 0)//优先级为0的技能是手动技能
					continue;
				if(t - s._lastSkillFailList[skill.skillId] < 200)//上次针对目标使用技能失败，时间间隔内不再使用这个技能
					continue;				
				if(s.isCDOk(skill))
					return skill;
			}
			return null;
		}
		/**释放技能*/
		public operSkill(skill:ISkillData,direction:number=-1):void
		{
			let s= this;				
			s.cdSkill(skill);

			s._ownerData = new OwnerData(s, skill, 0);			
			s.setOperSts(skill.skillCfg.action, direction==direction?direction:s._direction);				
			if(s.isTower())
				SoundManager.instance.play(`${Conf.sound}shoot${s.roleID}.mp3`, 0, 1,null,null,SoundData.BACKGROUND_SOUND);
		}
		public setSts(sts: number = 0, direction: number = -1): void {
			let s = this;			
			super.setSts(sts, direction);	
			// s.setActionInvert(direction);
			if (StsType.isDeadSts(s._sts)) {
				// if(s._cfg.deadSound)
				// 	SoundManager.instance.play(s._cfg.deadSound,0,1,null,null,SoundData.MULTI_CHANNEL);
				s._isDead = true;
				// GameDispatcher.instance.dispatchEventWith(CommonEventType.N_BATTLE_MONSTER_DEAD, false, s);//只针对怪物用
				s.outArea();
				// s.setName(null);
			}
			// s._attackFrameIndex = s._skinPart.curRate;
			if (StsType.attackAction(s._sts) && s._ownerData) {
				let t:number = s._scene.timeTick;					
				let skillCfg:SkillCfg;					
				skillCfg = s._ownerData._skillData.skillCfg;
				if(skillCfg.action != s._sts) return;//技能动作不一致														
				
				s.operSkillEffect(s._ownerData);
				
				//动作速率(例如攻速)
				s._skinPart.playRate = s.buffValues[BuffEType.ATK_SPEED]?(1 + s.buffValues[BuffEType.ATK_SPEED].value):1;
			}	
		}
		/**释放技能特效*/
		public operSkillEffect(ownerData:OwnerData):void
		{
			let s = this;
			let skillCfg:SkillCfg;
			let t:number;
			t = s._scene.timeTick;			
			skillCfg = ownerData._skillData.skillCfg;	
			if(skillCfg.attackEffect && skillCfg.attackEffect.length > 0)
			{
				let tX:number,tY:number;
				let len:number;
				// if(skillCfg.condition == PeakType.LOCK_POSITION && s.warnSkillPos){							
				// 	//如果是锁定位置的技能，弹道特效需要根据锁定的位置来落点
				// 	len = s.warnSkillPos.length;
				// 	if(len > 0)
				// 	{
				// 		while(len > 1)
				// 		{								
				// 			tX = s.warnSkillPos[len - 2];
				// 			tY = s.warnSkillPos[len - 1];
				// 			Effect.addEffect(s, ownerData,null,t, EffectType.ATTACK, skillCfg.attackEffect, tX, tY, s._direction);
				// 			len -= 2;
				// 		}	
				// 	}							
				// }
				// else{
					let r:GameRole;
					let targets:GameRole[];										
					if(s._targetRoles.length > 0)
					{
						targets = s.getAtkTarget();//通过getAtkTarget获取当前非失效的目标
						len = targets.length;
						while(--len>-1)
						{								
							r = targets[len]
							tX = r._absX;
							tY = r._absY;
							Effect.addEffect(s, ownerData, t, EffectType.ATTACK, skillCfg.attackEffect, tX, tY, s._direction, r._headJumpH*0.5, null, r);
						}	
					}						
					else
					{
						let deg:number = map2D.DirectionType.getDirectorDeg(s._direction);							
						tX = s._absX + MathUtil.cos(deg) * DriftObj.MAX_DIS;
						tY = s._absY + MathUtil.sin(deg) * DriftObj.MAX_DIS;
						Effect.addEffect(s, ownerData, t, EffectType.ATTACK, skillCfg.attackEffect, tX, tY, s._direction);
					}
				// }
								
			}

			// if(skillCfg.attackSound)
			// 	SoundManager.instance.play(skillCfg.attackSound);				
		}
		public isSkillCoolEnd(skillId:number):number
		{
			return 0;
		}
		/**获取攻击目标(调用此方法，当目标已经失效，则会从队列中排除)*/
		public getAtkTarget():GameRole[]
		{
			let s= this;
			let len:number;
			len = s._targetRoles.length;
			while(--len>-1)
			{
				if(s._targetRoles[len]._id != s._targetIds[0])
				{
					s._targetRoles.splice(len,1);
					s._targetIds.splice(len,1);
				}
					
			}
			return s._targetRoles;
		}
		public setCamp(camp: number): void {
			let s = this;			
			s._camp = camp;
		}
		public setOwner(val: AniRole): void {
			let s = this;
			s._owner = val;
			s.setCamp(val ? (<any>val)._camp : 0);
		}
		public getOwner(): Role {
			return this._owner?this._owner:this;
		}
		/**设置血条样式
		 * @param objID 样式id 参考Role.ID
		 * @param hideInterval 隐藏血条的时间间隔 默认NaN 不隐藏
		*/
		public setHpBar(objID: string, hideInterval:number=NaN): void {
			let s = this;			
			s.hpBar = <BarObj>RoleEffectFactory.addEffectTo(s, {objID:objID,height:20}, RoleEffectID.HPBAR);
			s.hpBar && (s.hpBar.hideInterval = hideInterval);
			s.setHp(s._hp, s._hpMax, s._shieldHp, false);
		}	
		public del(): boolean {
			let s = this;			
			if(!super.del())
				return false;
			s.setHpBar(null);
			// s.setName(null);
			return true;
		}
		/**设置此角色的拥有者数据（物体或者特效使用）*/
		public setOwnerData(ownerData:OwnerData):void
		{
			let s = this;			
			s._ownerData = ownerData;
			if(s._ownerData)
				s._camp = s._ownerData._camp;
			else
				s._camp = s._camp;
		}
		/**设置攻击目标*/
		public setAtkTarget(targets:GameRole[]):void
		{
			let s= this;		
			if(targets)
			{
				s._targetRoles = targets;
				s._targetIds.length = 0;
				let len:number;
				len = s._targetRoles.length;
				while(--len>-1)
				{
					s._targetIds[len] = s._targetRoles[len]._id;
				}
			}				
			else
			{
				if(s._targetRoles) s._targetRoles.length = 0;
				if(s._targetIds) s._targetIds.length = 0;
			}
			//目标改变绕路方向重置
			if(s._smartObj)
				s._smartObj.targetChange();
		}
		/**攻击目标是否合法，由于对象会被对象池回收，所以要判断id是否变更*/
		public targetIsValid():boolean
		{
			let s = this;
			if(s._targetRoles[0] == null)
				return false;			
			return s._targetRoles[0]._id == s._targetIds[0];
		}		
		/**获取攻击目标id*/
		public getAtkTargetIds():number[]
		{
			return this._targetIds;
		}
		/**获取朝向目标的向量(只算8个方向)*/
		public vecToTarget(target: GameRole): Laya.Point {
			let addX: number, addY: number;
			let s = this;
			if (target.col > s.col)
				addX = 1;
			else if (target.col < s.col)
				addX = -1;
			else
				addX = 0;
			if (target.row > s.row)
				addY = 1;
			else if (target.row < s.row)
				addY = -1;
			else
				addY = 0;
			PositionUtil._pt.x = addX;
			PositionUtil._pt.y = addY;
			return PositionUtil._pt;
		}
		public findTarget():Role
		{
			return null;
		}
		// public setMem(flag:number):void
		// {
		// 	let s= this;			
		// 	s._memFlag=flag;			
		// }
		public changeSmart(type:AIEnum):void
		{
			let s = this;
			if(s._smartType == type)
				return;	
			s._smartType = type;		
			s.outSmart();
			s.inSmart(type);			
		}
		/**进入某智能*/
		protected inSmart(type:AIEnum):void
		{
			let s= this;			
			s._smartObj = AIBase.create(type, {role:s});
			if(s._smartObj)
				s._smartObj.inSmart();			
		}
		/**取消某智能*/
		protected outSmart():void
		{
			let s= this;
			if(s._smartObj)
				s._smartObj.outSmart();
		}
		/**查询我对于角色的阵营标志 1-自己 2-友军 4-敌军
		 * @param id 角色唯一id
		 * @param camp 角色阵营类型
		 * @return 阵营标志
		*/	
		public getCampFlag(id:number, camp:number):number
		{
			let s= this;			
			if(s._ownerData)			
				return PublicVar.getCampFlag(s._ownerData._id, s._ownerData._camp, id, camp);
			return PublicVar.getCampFlag(s._id, s._camp, id, camp);
		}
		/**查询我对于角色r的阵营索引 0-自己 1-友军 2-敌军
		 * @param id 角色唯一id
		 * @param camp 阵营类型
		*/
		public getCampFlagIndex(id:number, camp:number):number
		{
			let s= this;
			if(s._ownerData)			
				return PublicVar.getCampFlagIndex(s._ownerData._id, s._ownerData._camp, id, camp);
			return PublicVar.getCampFlagIndex(s._id, s._camp, id, camp);
		}	
		/**对象是否可被攻击
		 * @param role 被攻击者
		 * @param checkCamp 检测的阵营标志 默认-1 不检测
		*/
		public canAttack(role: GameRole, checkCamp:number=-1): boolean {
			let s = this;
			if(role == null)return false;			
			if(checkCamp > -1 && (checkCamp & role.getCampFlag(s._id, s._camp)) == 0)
				return false;			
			return !role.isDel() && !StsType.cannotAction(role._sts);
		}
		/**重设针对目标的行走方向*/
		public resetTargetDir(target: Role, angleOffet: number = 0): void {
			let s = this;
			let tarAngle: number;
			tarAngle = PositionUtil.calculateAngle(target.absX, target.absY, s._absX, s._absY) + angleOffet;			
			s._targetAngle = tarAngle;
			s._targetDirection = map2D.DirectionType.getDirectorSts(tarAngle);
		}
		public setHasEnemyInRange(inRange:boolean){
			let s= this;
			s._hasEnemyInRange = inRange;			
		}
		public moveSmart(): void {				
			let s = this;
			let per: number;
			if (!s._targetMove)
				return;
			// if(s._followTarget)
			// {
			// 	s._absX = s._followTarget._absX + s._targetX;
			// 	s._absY = s._followTarget._absY + s._targetY;				
			// 	if (s._targetMove)
			// 		s.inArea();
			// 	if(!s._followTarget._hasTargetPos)
			// 	{
			// 		s._hasTargetPos = false;
			// 		s._followTarget = null;
			// 		s.moveSmartEnd();
			// 	}					
			// 	return;
			// }
			let ox: number, oy: number;			
			ox = s._absX;
			oy = s._absY;
			s.moveTimeTicker.playRateUpdate();
			per = s.moveTimeTicker.getPercent();
			if (per >= 1) {
				s._absX = s._targetX;
				s._absY = s._targetY;
				if(s._targetH == s._targetH)
					s._floatH = s._targetH;
				s._hasTargetPos = false;
				s._targetH = s._targetX = s._targetY = NaN;				
				s.moveSmartEnd();
			}
			else {
				s._absX -= s._speedX;
				s._absY -= s._speedY;
				s._speedX = (s._targetX - s._absX) * per;
				s._speedY = (s._targetY - s._absY) * per;					
				s._absX += s._speedX;
				s._absY += s._speedY;					
				
				if(s._targetH == s._targetH)
				{
					s._floatH -= s._speedH;
					s._speedH = (s._targetH - s._floatH) * per;
					s._floatH += s._speedH;
				}						
			}
				
			// if (s.rotateMove) {
			// 	let pt: egret.Point = GYLite.PositionUtil.rotationXY(0, s._headH >> 1, s._skin.rotation * GYLite.MathConst.ROTATION_ANGLE);
			// 	s._skin.x -= s._rotateXOffset;
			// 	s._skin.y -= s._rotateYOffset;
			// 	s._rotateXOffset = -pt.x;
			// 	s._rotateYOffset = -pt.y;
			// 	s._skin.x += s._rotateXOffset;
			// 	s._skin.y += s._rotateYOffset;
			// 	s._skin.rotation += 30;
			// }			
			
			if (s._targetMove)
				s.inArea();
		}
		public enterLoop(t:number,index:number):void
		{
			let s = this;
			super.enterLoop(t,index);
			if(s._scene.editabled)return;	
			if (!s.smartDisabled && s._smartObj != null && !StsType.isDeadSts(s._sts))
				s._smartObj.smart(t);
			return;
		}
		public beforeToPool(): void
		{
			super.beforeToPool();			
			let s= this;
			s._bodyRange.length = 0;
			s.removeBuff();
			if(s.buffList)s.buffList.length = 0;
			if(s.buffValues)s.buffValues.length = 0;			
		}		
		/**重载成按时间移动
		 * @param abX 坐标x
		 * @param abY 坐标y
		 * @param callBack 回调 默认null
		 * @param thisObj 对象 默认null
		 * @param sts 移动动作 默认StsType.RUN
		 * @param time 移动花费总时间（毫秒） 默认180
		 * @param rotateMove 是否旋转 默认false
		 * @param dir 方向 默认-1
		 * @param endSts 结束后恢复的动作 默认-1
		 * @param checkSts 是否检测当前状态是否可以移动，默认true
		 * @param floatH 移动高度
		*/
		public moveTo(abX: number, abY: number, callBack: any = null, thisObj: any = null, sts: number = StsType.RUN, time: number = 180, dir:number=-1,endSts:number=-1, checkSts:boolean=true, floatH:number=NaN): void {
			let s = this;
			if(s.isDel()) return;//标记死亡后返回
			if(checkSts && s._isDead)return;
			let agl: number, disX: number, disY: number;
			s._dirMove = false;
			
			disX = abX - s._absX;
			disY = abY - s._absY;

			if (sts > -1) {
				if(dir == -1)
				{
					agl = Math.atan2(disY,disX);
					dir = map2D.DirectionType.getDirectorSts(agl)
				}
				s.setSts(sts, dir);
			}
			s.moveFlagSet(true);
			disX = Math.pow(disX * disX + disY * disY, 0.5);
			s.moveTimeTicker.init(s._scene.timeTick - CommonUtil.delta, time);
			s._speedX = s._speedY = 0;
			s._targetX = abX;
			s._targetY = abY;
			s._targetH = floatH;
			s._hasTargetPos = s._targetX == s._targetX || s._targetY == s._targetY || s._targetH == s._targetH;
			s._moveEndCall = callBack;
			s._moveEndObj = thisObj;
			s._moveEndSts = endSts == -1?StsType.STAND:endSts;
		}
		/**往指定方向行走一步长*/
		public moveDir(agl: number, speed: number = NaN,ignoreMoveStopRole:Role=null): MoveState {
			let s = this;			
			let moveState: MoveState;
			moveState = super.moveDir(agl, speed,ignoreMoveStopRole);			
			if (moveState && moveState.result >= MoveResult.PASS)
				s.inArea();
			return moveState;
		}
		public create(createSts:number=StsType.STAND,createDir:number=0,x:number=0,y:number=0): void {
			super.create(createSts,createDir,x,y);
			let s = this;			
			s.inArea();			
			s._bornX = s._absX;
			s._bornY = s._absY;
			s.updateBodyRange();
		}

		/**血量显式变化(带数字)
		 * @param addHp 血量变化量
		 * @param isCritical 是否暴击	
		 * @param hpType 数字类型		 
		 * @param flowNum 是否指定血量飘字（优先级比boss虚假飘字高），默认NaN不指定
		 * @param shield 护盾血量变化量
		 * @param isDouble 是否连击
		*/
		public addHp(addHp: number, isCritical: boolean = false, hpType: number = 0, flowNum:number=NaN, shield:number=0): void {
			let s = this;			
			let numID: string, value:string;
			numID = RoleID.HP_NUM;
			
			s.setHp(s._hp + addHp,NaN, s._shieldHp + shield);			
			if(flowNum == flowNum)
				addHp = flowNum;
			
			if (addHp != 0)
			{					
				addHp = addHp<0?-addHp:addHp;
				value = s.chaneNumber(addHp);
				s.addFlowNumber(numID, value, 0, -s._headJumpH);
			}				
			if(shield != 0)
			{							
				shield = shield<0?-shield:shield;
				value = s.chaneNumber(shield);
				s.addFlowNumber(numID, value, 0, -s._headJumpH);
			}				
		}
		/**数值转换*/
		private chaneNumber(value: number):string{
			return (value < 0 ? "-" : "") + NumberUtil.bigNumToStr(Math.abs(value), 0);//小于0需要补上-号	
		}
		/**添加飘字封装一下
		 * @param objID 样式id 参考RoleID常量
		 * @param value 值
		 * @param x 坐标x 默认0
		 * @param y 坐标y 默认0
		 * @param hpType 飘字类型 默认HPNUM_TYPE.COMMON 
		*/
		public addFlowNumber(objID:string, value:string, x:number=0, y:number=0):void
		{
			let s = this;			
			s.addNumber({
				owner:null,
				hpType:WordEnum.COMMON,
				roleType:RoleType.NUMBER_OBJ,
				objID:objID,
				x:x,
				y:y,
				value:value
			});
		}
		/**给目标添加受击效果
		 * @param target 目标角色		 		 		 
		 * @return 是否成功命中
		*/
		public addHitToTarget(target:GameRole):boolean
		{
			let s = this;
			let atkData:TargetData;						
			let skillCfg:SkillCfg;
			if(target._isDead || target.isDel())
				return;
			skillCfg = s._ownerData._skillCfg;

			atkData = TargetData.create(skillCfg,FighterHurtType.common);
			atkData.role = target;	
			atkData.fId = s._ownerData._id;
			atkData.tId = target._id;
			atkData.isDouble = false;
			
			s.calHurt(skillCfg.skillNub, atkData);
			target.setDamage(-1,s._ownerData,atkData);
			s.addHitEffect(target, s._ownerData);						
			s.addBuffToTarget(target, skillCfg.buff);
			return true;
		}
		/**添加一个mmo战斗命中特效
		 * @param target 目标对象
		 * @param ownerData 技能数据拥有者
		 * **/
		protected addHitEffect(target:GameRole, ownerData:OwnerData):boolean
		{
			let s = this;
			if(target.isEnemyMonster())
			{
				SoundManager.instance.play(`${Conf.sound}monsterHit.mp3`, 0, 1,null,null,SoundData.BACKGROUND_SOUND);
			}
			else
			{
				let lv:number;
				lv = target.level >=1 && target.level<=5?target.level:5;
				SoundManager.instance.play(`${Conf.sound}hit${lv}.mp3`, 0, 1,null,null,SoundData.BACKGROUND_SOUND);
			}
			if(ownerData._skillCfg.hitEffect && ownerData._skillCfg.hitEffect.length > 0)
			{
				Effect.addEffect(target, s._ownerData, s._scene.timeTick, EffectType.SINGLE, ownerData._skillCfg.hitEffect, NaN, NaN, 0, NaN, s, target);
				return true;
			}
			return false;				
		}
		/**设置即时战斗受击
		 * @param damageSts 受击表现的动作状态		 
		 * @param atkOwnerData 攻击方相关数据
		 * @param targetData 目标数据
		 * @param hitBackArr 击退参数
		*/
		public setDamage(damageSts: number = -1, atkOwnerData: OwnerData=null, targetData: TargetData=null): void 
		{
			let s = this;
			s.calDamage(atkOwnerData, targetData);
			targetData.clear();			
		}	
		/**计算即时战斗伤害
		 * @param atkOwnerData 攻击方相关数据
		 * @param targetData 目标数据
		*/
		public calDamage(atkOwnerData: OwnerData, targetData: TargetData):void
		{
			let s = this;						
			if(atkOwnerData == null || targetData == null)
				return;
			
			s.addHp(-targetData.dmgRealHurt);
			s.checkDead(atkOwnerData);
		}	
		/**计算技能伤害,当返回伤害为0则表示触发伤害
		 * @param hurt 伤害		 
		 * @param atkData 攻击目标的数据
		*/
		protected calHurt(hurt:number,atkData:TargetData):number
		{
			atkData.dmgRealHurt = hurt;
			return hurt;
		}
		/**根据buff配置添加buff
		 * @param target 目标角色
		 * @param buff buff配置 [buff类型，数值，持续时间]		 
		*/
		protected addBuffToTarget(target:GameRole, buff:number[][]):void
		{
			if(buff == null)return;
			let i:number,len:number;
			let buffParams:number[];			
			let s = this;			
			let o:GameRole = <GameRole>s.getOwner();
			len = buff.length;
			for(i=0;i<len;++i)
			{
				buffParams = buff[i];				
				target.addBuff(buffParams, o.buffRandAdd);
			}			
		}
		public addBuff(buffParams:number[], buffRandAdd:number=0):void
		{
			let s= this;	
			let t:number;
			let type:number;
			if(s.buffValues[type])
				return;
			let rand:number = Math.min(Main.gameConfig.buffRandMax?Main.gameConfig.buffRandMax:0.5, (buffParams[5]?buffParams[5]:1) + buffRandAdd);
			let r = Math.random();			
			if(r > rand)return;
			type = buffParams[0];
			t = s._scene.timeTick;
			s.buffValues[type] = {type:type, value:buffParams[1], endTime:t + buffParams[2],lastAffectTime:(buffParams[3]>0?0:NaN),affectInterval:buffParams[3],buffEffectID:buffParams[4]}				
			s.buffList.push(type);
			if(type == BuffEType.LIMIT)//静止
			{
				s.pause();
			}
			else if(type == BuffEType.ATK_SPEED && StsType.attackAction(s._sts))//攻速
			{
				//动作速率(例如攻速)
				s._skinPart.playRate = s.buffValues[BuffEType.ATK_SPEED]?(1 + s.buffValues[BuffEType.ATK_SPEED].value):1;
			}
			if(buffParams[4] > 0)
			{	
				let len:number;
				len = s.buffObjs.length;
				while(--len>-1)				
				{
					if(s.buffObjs[len].roleID == String(buffParams[4]))
						break;
				}
				if(len == -1)
					s.buffObjs.push(s._scene.createEffectToScene(s, String(buffParams[4]), 0, 0, EffectType.BUFF, 0, 0, map2D.LayerType.ROLE_FRONT));
			}
		}
		public removeBuff(effectID:string=null):void
		{
			let len:number;
			let s = this;
			let buffObj:ObjBase;
			if(s.buffObjs)
			{
				len = s.buffObjs.length;
				while(--len>-1)
				{
					if(effectID == null || s.buffObjs[len].roleID == effectID)
					{
						buffObj = s.buffObjs[len];						
						buffObj.del();
						if(effectID)
							s.buffObjs.splice(len, 1);						
					}
				}
				if(effectID==null)
					s.buffObjs.length = 0;
			}			
		}
		public checkDead(atkOwnerData: OwnerData=null, buffData:IBuffData=null):void
		{
			let s= this;
			if(s._hp <= 0 && !StsType.cannotAction(s._sts))
			{
				s._isDead = true;		
				s.battleDead(atkOwnerData, buffData);
			}
		}	
		private battleDead(atkOwnerData: OwnerData=null, buffData:IBuffData=null):void
		{
			let s = this;			
			s.setOperSts(StsType.DEATH);
			s._scene.sceneLogic.roleDead(s,atkOwnerData, buffData);
			// if(GameManager.debug){
			// 	Log.writeLog("打印战斗数据，状态死亡" + " 角色id:" + s._roleID);
			// }
		}
		public getAttackRangeMax(skill:ISkillData):number
		{
			let s= this;			
			let stsCfg:any;
			if(skill.skillCfg.skillRange == -1)
			{
				stsCfg = s._clothesConfig[skill.skillCfg.action];
				if(stsCfg)
				{
					let atkMaxDis:number = stsCfg.rate[0].atkMaxDis;
					if(atkMaxDis > 0)
						return atkMaxDis;
				}
			}			
			return skill.skillCfg.skillRange;	
		}
		public findEnemy(skill:ISkillData):GameRole[]
		{
			let s = this;
			let arr:GameRole[],tempArr:GameRole[];
			let o:GameRole;
			o = <GameRole>s.getOwner();
			tempArr = [];
			if(o._camp == CampType.CAMP_1)
				arr = s._scene.getMonsterList2();
			else
			{
				arr = [];
				let logic:CommonScene = <CommonScene>s._scene.sceneLogic;
				if(logic.isDoorValid())
					arr.push(logic._curDoor);
				else if(logic.isBedValid())
					arr.push(logic._curBed);								
			}
			let len:number;
			let r:GameRole;
			let dis:number;
			len = arr.length;
			while(--len > -1)
			{
				r = arr[len];
				if(r.isTower())
					continue;
				dis = s.inMyRange(r, s.maxSkillRange);
				r.tempDis = dis;				
				if(dis == Number.MAX_VALUE)
					continue;	
				tempArr[tempArr.length]	= r;
			}			
			tempArr.sort(PeakType.sortFuncs[PeakType.MIN_DISTANCE]);
			return tempArr;
		}
		/**是否在我的范围内(同时在视野和领地范围内)
		 * @param target 对比目标
		 * @param skillRange 使用的技能，默认0，不叠加技能范围
		 * @return 返回与目标的最近距离的平方（通过目标的受击范围计算），如果不在范围内则返回Number.MAX_VALUE
		*/
		public inMyRange(target:GameRole, skillRange:number=0):number
		{
			let territoryRange:number, viewRange:number;
			let dis:number,dis2:number;
			let s = this;			
			//领地范围判断(领地范围+技能攻击范围)
			territoryRange = s._territoryRange2;			
			dis2 = PositionUtil.calculateDistance2(target._absX,target._absY,s._bornX,s._bornY) + skillRange;
			
			if(dis2 > territoryRange)
				return Number.MAX_VALUE;
			//视野范围判断			
			viewRange = s._viewRange2;
			dis = PositionUtil.calculateDistance2(target._absX,target._absY,s._absX,s._absY);			
			if(dis > viewRange)
				return Number.MAX_VALUE;
			
			return dis;			
		}
		/**过滤在技能的最大攻击范围内的对象
		 * @param targets 目标对象列表
		 * @param range 范围保证能攻击到的最大距离		 
		*/
		public filterInMaxAtkRange(targets:GameRole[], range:number):GameRole[]
		{
			let i:number,len:number;
			let s = this;
			let arr:GameRole[]=[];
			let r:GameRole;
			//为保证优先顺序，此处不能用倒序
			len = targets.length;
			for(i=0;i<len;++i)
			{
				r = targets[i];
				if(s.inMaxAtkRange(r, range))									
					arr[arr.length] = r;				
			}
			return arr;
		}	
		/**对方是否在技能的最大攻击范围内
		 * @param target 攻击对象
		 * @param range 最小攻击距离		 
		*/
		public inMaxAtkRange(target:GameRole, range:number):boolean
		{
			let s= this;
			let arr:number[];
			let i:number,len:number,dis:number,minDis:number;
			minDis = Number.MAX_VALUE;
			arr = target.getBodyRange(target._direction);
			len = arr.length;
			for(i=0;i<len;i+=2)
			{
				dis = PositionUtil.calculateDistance2(arr[i],arr[i+1],s._absX,s._absY);
				if(dis < minDis)				
					minDis = dis;				
			}
			dis = PositionUtil.calculateDistance2(target._absX,target._absY,s._absX,s._absY);			
			if(dis < minDis)				
				minDis = dis;
			return minDis < range * range;
		}	
		/**获取自身碰撞盒子
		 * @param dir 朝向 给不同方向分不同受击范围，暂时没用
		 * @param useMyPos 是否用自己的世界坐标定位，默认true，否则返回相对坐标，并不是世界坐标
		 * @param toX 偏移x
		 * @param toY 偏移y
		*/
		public getBodyRange(dir:number=0,useMyPos:boolean=true,toX:number=NaN,toY:number=NaN):number[]
		{
			let s= this;
			if(toX == toX && toY == toY)
			{
				let i:number,len:number;				
				let range:number[] = [];
				let hitRange:number[];
				hitRange = s.skinPart.hitRange;				
				len = hitRange.length;
				for(i=0;i<len;i+=2)
				{
					range[i] = toX + hitRange[i];
					range[i+1] = toY + hitRange[i+1];
				}
				return range;
			}
			else if(useMyPos)
			{				
				return s._bodyRange;
			}
			else
			{				
				return s._hitRange;				
			}						
			
		}
		/**更新受击范围的世界坐标定位*/
		protected updateBodyRange():void
		{
			let aX:number,aY:number,i:number,len:number;
			let s = this;
			let range:number[] = s._bodyRange;
			let hitRange:number[];
			if(s._clothesRate.hitRange == null)
				return;
			hitRange = s._clothesRate.hitRange[s.skinPart.curRate];
			if(hitRange == null)
				hitRange = s._clothesRate.hitRange[0];
			s._hitRange = hitRange;
			s._bodyMinDis = s._clothesRate.bodyMinDis?s._clothesRate.bodyMinDis[0]:32;
			aX = s._absX;
			aY = s._absY;
			len = hitRange.length;
			for(i=0;i<len;i+=2)
			{
				range[i] = aX + hitRange[i];
				range[i+1] = aY + hitRange[i+1];
			}			
		}
		/**给角色添加技能数据*/
		public addSkillData(obj:ISkillData):void
		{
			let s = this;			
			s._skillList.push(obj);
		}
		public clearSkillList():void
		{
			let s= this;
			s._skillList.length = 0;			
		}
		/**技能信息变更，执行按优先级排序，计算出所有技能最大距离*/
		public skillDataChange():void
		{
			let s= this;
			s._skillList.sort((a:ISkillData,b:ISkillData):number=>{
				if(a.skillCfg.priority > b.skillCfg.priority)
					return -1;
				return 1;
			});
			let len:number;			
			let max:number = 0;
			len = s._skillList.length;
			while(--len>-1)
			{
				max = Math.max(s.getAttackRangeMax(s._skillList[len]),max);
				// s._skillToFlag |= s._skillList[len].skillCfg.campFlag;
			}
			s.maxSkillRange = max;
			// if (s.isMyPlayer){				
			// 	GameDispatcher.instance.dispatchEventWith(CommonEventType.N_BATTLE_PLAYER_SKILL, false, s);
			// }
		}		
		/**设置血量
		 * @param val 血量
		 * @param max 最大血量，默认NaN不设置
		 * @param shield 护盾值，默认NaN不设置
		 * @param tween 是否带tween动画，默认true
		*/
		public setHp(val: number, max: number = NaN, shield:number=NaN,tween:boolean=true): void {
			let s = this;
			// let mod: PlayerModel = PlayerModel.getInstance();
			if (max == max) {
				if (s._hpMax != max) {
					s._hpMax = max;
					// if (s.isMyPlayer){
					// 	mod.hp = s._hp || 0;
					// 	mod.maxHp = s._hpMax || 0;						
					// }
					s._attriCallFlag |= AttriCallType.HPMAX;
				}

			}
			val = Math.max(s.getMinHp(),Math.min(s._hpMax, val));
			if (val != s._hp) {
				s._hp = val;
				// if (s.isMyPlayer){
				// 	mod.hp = s._hp || 0;
				// 	mod.maxHp = s._hpMax || 0;					
				// }				
				s._attriCallFlag |= AttriCallType.HP;
			}
			if(shield == shield)
			{
				if (shield != s._shieldHp)
				{	
					if(shield < 0)			
						shield = 0;
					s._shieldHp = shield;				
					s._attriCallFlag |= AttriCallType.HPSHIELD;
				}
			}			
			

			if (s.hpBar) {
				s.hpBar.setHp(s._hp, s._hpMax, s._shieldHp, tween);
			}
			s._isDead = !(s._hp > 0);//当血量大于0时，重置死亡标志，不允许出现hp大于0的死亡状态
			if(!s._isDead && StsType.cannotAction(s._sts))			
				s.setSts(StsType.STAND, s._direction);
		}
		/**添加飘字*/
		public addNumber(numberData:INumberData):void
		{
			let s= this;
			s._numberList[s._numberList.length] = numberData;
		}
		/**移除飘字*/
		public removeNumber(numberObj:NumberObj = null):void
		{
			let len:number;
			let s= this;
			if(numberObj == null)
			{
				s._numberList.length = 0;
				return;
			}
			len = s._numberList.length;
			while(--len>-1)
			{
				if(s._numberList[len].id == numberObj._id)
				{
					s._numberList.splice(len, 1);
					break;
				}
			}
		}
		public numberLoop(t:number):void
		{
			let s = this;
			let numberData:INumberData;
			numberData = s._numberList[0];
			if(numberData)
			{				
				let num:NumberObj;
				let i:number,len:number,offsetX:number,offsetY:number;
				let numSkin:ILabelData;
				let spdPer:number,interval:number,lastInterval;
				len = s._numberList.length;
				spdPer = 10/len;
				if(spdPer > 1)
					spdPer = 1;
				interval = PublicVar.hpInterval * spdPer;
				
				lastInterval = t - s._lastFlowNumTime;			
				if(lastInterval >= interval)
				{	
					offsetX = numberData.x + s._absX + (lastInterval>1000?0:(Math.random()*80-40)|0);
					offsetY = numberData.y + s._absY;// + (s._scene._isMMO?-Math.random()*10:0)|0;
					numSkin = s._camp == CampType.CAMP_1?SkinDictionary.fillNum2:SkinDictionary.fillNum;
					num = s._scene.createNumberObj(numberData.owner, numberData.roleType, numberData.objID, offsetX, offsetY, numberData.value, numSkin);
					num._skinPart.duration = Math.max(400,num._skinPart.duration*spdPer);
					numberData.id = num._id;
					s._lastFlowNumTime = t;
					s._numberList.shift();
				}
				
			}
		}
		/**属性变更通知*/
		protected attriCall():void
		{
			let s = this;
			AttriCall.call(s, s._attriCallFlag);		
			s._attriCallFlag = 0;	
		}
		//获取最小血量
		protected getMinHp(): number {
			return 0;
		}
		/**获取属性*/
		public getAttr(type: AttriItemDefEnum): number {
			let val = this._typesAttr && this._typesAttr[type];
			return val == null ? 0 : val;
		}
		/**设置属性，重置参数为number[]*/
		public setAttr(typesAttr:number[]):void
		{
			let s= this;
			s._typesAttr = typesAttr;
			let type:number;
			type = s._typesAttr[AttriItemDefEnum.atk_m] || s._typesAttr[AttriItemDefEnum.atk_w] || s._typesAttr[AttriItemDefEnum.atk];
			if(s._typesAttr[type])
				s._atk = s._typesAttr[type];			
		}
		public exitLoop(t: number, index: number): void {
			let s = this;
			super.exitLoop(t, index);
			s.attriCall();		
			s.numberLoop(t);	
			// if (s._sts >= StsType.ATTACK)
			// 	s.attacking();
			let len:number,ind:number;
			let buffData:IBuffData;
			len = s.buffList.length;
			while(--len>-1)
			{
				ind = s.buffList[len];
				buffData = s.buffValues[ind];
				if(buffData == null)continue;
				if(buffData.type == BuffEType.HURT)
				{					
					if(t - buffData.lastAffectTime > buffData.affectInterval)
					{
						if(!s._isDead)
						{
							s.addHp(-buffData.value);
							s.checkDead(null, buffData);
						}						
						buffData.lastAffectTime = t;
					}					
				}
				if(t >= buffData.endTime)
				{
					if(buffData.type == BuffEType.LIMIT)//静止					
						s.resume();					
					else if(buffData.type == BuffEType.ATK_SPEED)//攻速
						s._skinPart.playRate = 1;
					s.buffList.splice(len, 1);
					s.buffValues.splice(ind, 1);
					if(buffData.buffEffectID > 0)
						s.removeBuff(""+buffData.buffEffectID);
				}
			}
		}
		public resetLevelUpCost():void
		{
			let s= this;
			let arr:any;
			if(s.isTower())//防御塔升级
			{
				s.levelUpCost = Main.getTowerLvUpCost(s._roleID);
				return;
			}
			if(s.isBed())//床升级
				arr = Main.gameConfig.bedLvConfig;				
			else if(s.isDoor())//门升级
				arr = Main.gameConfig.doorLvConfig;							
			if(arr)
				s.levelUpCost = arr[s.level]?arr[s.level].cost:NaN;
		}
		protected attacking(): boolean {
			return false;
		}
		/**设置角色数据(角色属性和技能)*/
		public static roleDataSet(r:GameRole, obj:any):void
		{
			let hp:number = obj.hp?obj.hp:100;			
			if(obj.hp > 0)
			{
				r.setHp(hp, hp);
				r.setHpBar(RoleID.HP_BAR_GREEN);
			}				
			let attrs:number[] = [];					
			attrs[AttriItemDefEnum.atk] = obj.attack;
			attrs[AttriItemDefEnum.hp] = obj.hp;
			r.setAttr(attrs);					
			if(obj.skillList && obj.skillList.length > 0)
			{
				let i:number,len:number, skillId:number;
				let skillData:ISkillData;
				let skillCfg:SkillCfg;
				len = obj.skillList.length;
				for(i=0;i<len;++i)
				{
					skillId = obj.skillList[i];
					skillCfg = SkillConfig.getSkill(skillId);
					skillData = {skillId:skillId, cd:skillCfg.cd, skillCfg:skillCfg, preCD:0};
					r.addSkillData(skillData);
				}
				r.skillDataChange();
			}		
			else
				SkillCfg.addDefaultSkill(r, 1);			
			r.level = obj.level?obj.level:1;
			r.setCamp(obj.camp?obj.camp:CampType.NONE);		
			if(obj.speed)	
				r.speed = obj.speed;			
			if(obj.roomIndex!=null)	
				r.roomIndex = obj.roomIndex;	
			r.resetLevelUpCost();				
		}

		public get level():number
		{
			return this._level;
		}
		public set level(val:number)
		{
			this._level = val;
		}
		/**是否床*/
		public isBed():boolean
		{						
			return Main.gameConfig.bedIDs.indexOf(this._roleID) > -1;
		}
		/**是否门*/
		public isDoor():boolean
		{
			return Main.gameConfig.doorIDs.indexOf(""+this._roleID) > -1;
		}
		/**是否防御塔*/
		public isTower():boolean
		{
			return Main.gameConfig.towerIDs.indexOf(""+this._roleID) > -1;
		}
		/**是否怪物*/
		public isEnemyMonster():boolean
		{
			return Main.gameConfig.levelMonsterIDs.indexOf(""+this._roleID) > -1;
		}
		public outPoolInit(): void {
			super.outPoolInit();
			let s = this;			
			s._atk = s._lastFlowNumTime = s._attriCallFlag = 0;            
			s._shieldHp = 0;
			s._owner = s;
			s._targetRoles = [];
			s._targetIds = [];			
			s.cdReduce = 0;
			s.buffRandAdd = 0;
			s.levelUpCost = 0;
			s.setHasEnemyInRange(false);
			// s._playbackRate = 1;						
		}
		protected _level:number;
		public _camp:number;
		public isMyPlayer:boolean;
		public _typesAttr: {[type: number]: number};
		// public _campObj:any;
		/**属性变更通知(统一在出帧通知)*/
		protected _attriCallFlag:number;
		public _shieldHp:number;
		public _atk:number;
		public _hp:number;
		public _hpMax:number;		
		public tempDis:number;				
		protected _smartType:number;
		/**当前智能函数*/protected _smartObj:AIBase;
		/**是否战斗状态(1秒内存被攻击或者存索敌目标)*/public inBattleState:boolean;
		// protected _smartFunc:Function;
		public power:number;		
		public powerLv:number;
		protected _canRevive:boolean;
		/**附近有没有敌人*/
		public _hasEnemyInRange:boolean;		
		public _moveStopRole:GameRole;
		/**锁定的目标列表*/public _targetRoles:GameRole[];
		/**锁定的目标id列表*/protected _targetIds:number[];
		/**上次技能查询目标失败的时间*/public _lastSkillFailList:{[skillId:number]:number};
		/**技能的cd列表*/protected _skillCDList:{[skillId:number]:number};		
		/**技能的前置cd列表*/protected _skillPreCDList:{[skillId:number]:number};		
		/**技能列表*/public _skillList:Array<ISkillData>;
		// public expressLab:ExpressLabel;
		/**当前应该朝向目标的角度*/public _targetAngle: number;
		/**当前应该朝向目标的方向*/public _targetDirection: number;
		/**领地范围*/public territoryRange:number;
		/**领地范围平方*/private _territoryRange2:number;
		/**视野范围*/public viewRange:number;
		/**视野范围平方*/private _viewRange2:number;
		/**转成世界坐标的受击范围*/protected _bodyRange:number[];
		/**配置的受击范围*/protected _hitRange:number[];
		/**受击区域碰撞最小距离*/public _bodyMinDis:number;
		/**是否禁用智能*/public smartDisabled:boolean;
		/**血条*/public hpBar: BarObj;
		protected _numberList:INumberData[];
		protected _lastFlowNumTime:number;
		public maxSkillRange:number;
		public buffValues:IBuffData[];		
		public buffList:number[];
		public buffObjs:ObjBase[];
		/**cd缩减，默认1，0.5等于50%*/public cdReduce:number;
		/**buff概率增益，默认0，0.5等于50%*/public buffRandAdd:number;
		public levelUpCost:number;
		/**所属的房间索引*/
		public roomIndex:number;
	}

}